/********************************************************************************
 * Copyright(c) 2020-2025 VINCENT_WY All rights reserved.
 * - Filename
 * - Author  Vincent
 * - Version V1.0.0
 * - Date    2022/10/11
 * - Brief
 * - FunctionList:
 ******************************************************************************
 * History:
 *
 *
 *
 ******************************************************************************
 */
#include <iostream>
#include <string>
#include <fstream>
#include <sys/time.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include "lpc/LidarFrame.pb.h"
#include "google/protobuf/util/delimited_message_util.h"
/* parama define describe -----------------------------------------------------*/
uint64_t getCurrenTimeMs();
/* class describe -----------------------------------------------------*/
int main(int argc, char *argv[])
{
    lpc::LidarProtoPointCloud protoFrame;

    const char *filename = argv[1];
    std::string fileNameStr = filename;
    std::cout << "input file: " << filename << std::endl;
    std::fstream input(filename, std::ios::in | std::ios::binary);
    if (!input)
    {
        return -1;
    }
    uint64_t time1 = getCurrenTimeMs();

    std::ifstream m_dbFile;
    std::shared_ptr<google::protobuf::io::IstreamInputStream> _inDbStream{nullptr};

    m_dbFile.open(fileNameStr, std::ios::in | std::ios::binary);
    _inDbStream = std::make_shared<google::protobuf::io::IstreamInputStream>(&m_dbFile);

    bool clean_eof{false};
    auto frame = std::make_shared<lpc::LidarProtoPointCloud>();
    auto ok = google::protobuf::util::ParseDelimitedFromZeroCopyStream(frame.get(), _inDbStream.get(), &clean_eof);

    if (!ok && clean_eof)
    {
        std::cout << "Failed to parse address book." << std::endl;
        return 0;
    }
    uint64_t time2 = getCurrenTimeMs();
    std::cout << " points: " << frame->height() << std::endl;
    pcl::PointCloud<pcl::PointXYZI> cloud;
    uint64_t timestamp = frame->timestamp();
    cloud.width = frame->width();
    cloud.height = frame->height();
    cloud.is_dense = frame->is_dense();
    for (int index = 0; index < frame->data_size() / 4; index++)
    {
        pcl::PointXYZI point;
        point.x = frame->data(4 * index + 0);
        point.y = frame->data(4 * index + 1);
        point.z = frame->data(4 * index + 2);
        point.intensity = frame->data(index + 3);
        cloud.points.push_back(point);
    }
    std::string pcd_file_name = "";
    pcd_file_name.append("./");
    pcd_file_name.append(std::to_string(timestamp));
    pcd_file_name.append(".pcd");
    pcl::io::savePCDFileBinary(pcd_file_name, cloud);

    uint64_t time3 = getCurrenTimeMs();
    printf("%ld %ld\r\n", time2 - time1, time3 - time2);
    return 0;
}

uint64_t getCurrenTimeMs()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
/************************ (.cpp) END OF FILE ************************************/